package modules

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"mime"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// 生成随机代码
func generateCode() string {
	b := make([]byte, 8)
	_, err := rand.Read(b)
	if err != nil {
		return ""
	}
	return hex.EncodeToString(b)
}

// 处理临时文件上传
func TempUploadHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "只支持 POST 请求", http.StatusMethodNotAllowed)
		return
	}

	// 解析 multipart 表单
	err := r.ParseMultipartForm(32 << 20) // 32MB
	if err != nil {
		http.Error(w, "解析表单失败", http.StatusBadRequest)
		return
	}

	file, handler, err := r.FormFile("file")
	if err != nil {
		http.Error(w, "获取文件失败", http.StatusBadRequest)
		return
	}
	defer file.Close()

	// 生成随机代码
	code := generateCode()
	if code == "" {
		http.Error(w, "生成代码失败", http.StatusInternalServerError)
		return
	}

	// 创建临时目录
	tempDir := filepath.Join(config.Temp.Path, code)
	err = os.MkdirAll(tempDir, 0755)
	if err != nil {
		http.Error(w, "创建目录失败", http.StatusInternalServerError)
		return
	}

	// 保存文件
	filePath := filepath.Join(tempDir, "data")
	out, err := os.Create(filePath)
	if err != nil {
		http.Error(w, "创建文件失败", http.StatusInternalServerError)
		return
	}
	defer out.Close()

	fileSize, err := io.Copy(out, file)
	if err != nil {
		http.Error(w, "保存文件失败", http.StatusInternalServerError)
		return
	}

	// 保存元数据
	meta := TempFileMeta{
		Filename:   handler.Filename,
		UploadTime: time.Now(),
		FileSize:   fileSize,
	}
	metaData, err := json.Marshal(meta)
	if err != nil {
		http.Error(w, "生成元数据失败", http.StatusInternalServerError)
		return
	}
	metaPath := filepath.Join(tempDir, "meta.json")
	err = os.WriteFile(metaPath, metaData, 0644)
	if err != nil {
		http.Error(w, "保存元数据失败", http.StatusInternalServerError)
		return
	}

	// 返回代码
	w.WriteHeader(http.StatusCreated)
	fmt.Fprintf(w, `{"code": "%s"}`, code)
}

// 处理临时文件查询
func TempGetHandler(w http.ResponseWriter, r *http.Request) {
	code := strings.TrimPrefix(r.URL.Path, "/temp/get/")
	if code == "" {
		http.Error(w, "缺少代码", http.StatusBadRequest)
		return
	}

	metaPath := filepath.Join(config.Temp.Path, code, "meta.json")
	metaData, err := os.ReadFile(metaPath)
	if err != nil {
		http.Error(w, "文件不存在", http.StatusNotFound)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.Write(metaData)
}

// 处理临时文件下载
func TempDownloadHandler(w http.ResponseWriter, r *http.Request) {
	code := strings.TrimPrefix(r.URL.Path, "/temp/download/")
	if code == "" {
		http.Error(w, "缺少代码", http.StatusBadRequest)
		return
	}

	filePath := filepath.Join(config.Temp.Path, code, "data")
	file, err := os.Open(filePath)
	if err != nil {
		http.Error(w, "文件不存在", http.StatusNotFound)
		return
	}
	defer file.Close()

	// 获取元数据
	metaPath := filepath.Join(config.Temp.Path, code, "meta.json")
	metaData, err := os.ReadFile(metaPath)
	if err != nil {
		http.Error(w, "元数据不存在", http.StatusNotFound)
		return
	}
	var meta TempFileMeta
	err = json.Unmarshal(metaData, &meta)
	if err != nil {
		http.Error(w, "解析元数据失败", http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", meta.Filename))
	w.Header().Set("Content-Type", "application/octet-stream")
	io.Copy(w, file)
}

// 从指定 URL 下载临时文件
func TempUploadFromURL(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "只支持 POST 请求", http.StatusMethodNotAllowed)
		return
	}

	// 解析请求体中的 URL 参数
	urlParam := r.FormValue("url")
	if urlParam == "" {
		http.Error(w, "缺少 URL 参数", http.StatusBadRequest)
		return
	}

	// 生成随机代码
	code := generateCode()
	if code == "" {
		http.Error(w, "生成代码失败", http.StatusInternalServerError)
		return
	}

	// 创建临时目录
	tempDir := filepath.Join(config.Temp.Path, code)
	err := os.MkdirAll(tempDir, 0755)
	if err != nil {
		http.Error(w, "创建目录失败", http.StatusInternalServerError)
		return
	}

	// 发起 HTTP 请求下载文件
	resp, err := http.Get(urlParam)
	if err != nil {
		http.Error(w, "下载文件失败: "+err.Error(), http.StatusInternalServerError)
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		http.Error(w, "下载文件失败，HTTP 状态码: "+resp.Status, http.StatusInternalServerError)
		return
	}

	// 保存文件
	filePath := filepath.Join(tempDir, "data")
	out, err := os.Create(filePath)
	if err != nil {
		http.Error(w, "创建文件失败", http.StatusInternalServerError)
		return
	}
	defer out.Close()

	fileSize, err := io.Copy(out, resp.Body)
	if err != nil {
		http.Error(w, "保存文件失败", http.StatusInternalServerError)
		return
	}

	// 提取文件名
	filename := filepath.Base(urlParam)
	// 解析 Content-Disposition 头获取更准确的文件名
	if cd := resp.Header.Get("Content-Disposition"); cd != "" {
		if _, params, err := mime.ParseMediaType(cd); err == nil {
			if name := params["filename"]; name != "" {
				filename = name
			}
		}
	}

	// 保存元数据
	meta := TempFileMeta{
		Filename:   filename,
		UploadTime: time.Now(),
		FileSize:   fileSize,
	}
	metaData, err := json.Marshal(meta)
	if err != nil {
		http.Error(w, "生成元数据失败", http.StatusInternalServerError)
		return
	}
	metaPath := filepath.Join(tempDir, "meta.json")
	err = os.WriteFile(metaPath, metaData, 0644)
	if err != nil {
		http.Error(w, "保存元数据失败", http.StatusInternalServerError)
		return
	}

	// 返回代码
	w.WriteHeader(http.StatusCreated)
	fmt.Fprintf(w, `{"code": "%s"}`, code)
}
